package com.naiterui.ehp.bs.patient.controller;

import com.naiterui.ehp.bp.constants.SwaggerTag;
import com.naiterui.ehp.bp.support.context.ResourceHolder;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.support.exception.PublicService;
import com.naiterui.ehp.bp.support.exception.ResponseVO;
import com.naiterui.ehp.bp.support.security.SettingConfig;
import com.naiterui.ehp.bp.support.utils.JsonMapper;
import com.naiterui.ehp.bp.utils.biz.NameUtils;
import com.naiterui.ehp.bs.patient.exception.ExceptionCodes;
import com.naiterui.ehp.bs.patient.prodocl.MPatientDocument;
import com.naiterui.ehp.bs.patient.service.IPatientDocumentService;
import com.naiterui.ehp.bs.patient.service.IPatientService;
import com.naiterui.ehp.bs.patient.utils.cache.CommonCacheUtil;
import com.naiterui.ehp.bs.patient.utils.exception.PatientBusinessException;
import com.naiterui.ehp.bs.patient.vo.patient.PatientVO;
import com.naiterui.ehp.bs.patient.vo.requestparam.DeleteDocument;
import com.naiterui.ehp.bs.patient.vo.requestparam.PatientBaseParam;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

/**
 * 患者基础信息接口服务
 *
 * @version 2015年6月18日 下午5:09:49 by Amber
 * @Description 提供患者用户的创建、与B2C业务用户信息的对接、患者基础信息的编辑查询，患者档案信息的查询编辑。
 * @see
 */
@Api(tags = SwaggerTag.PATIENT + SwaggerTag.USER_INFO)
@RequestMapping("ap/patient")
@Controller
public class ApPatientController {

    private static final Logger LOGGER = LoggerFactory.getLogger(ApPatientController.class);

    @Autowired
    private IPatientService patientService;
    @Autowired
    private IPatientDocumentService patientDocumentService;

    /**
     * 登录
     * 患者端没有显示的登录流程,拿用户openId直接获取用户信息,含b2c用户信息。
     *
     * @param openId 微信openId
     *
     * @return
     *
     * @throws BusinessException String <用户账号异常>
     * @History 2015年6月19日 上午11:43:18 by Amber
     */
    @ResponseBody
    @RequestMapping("login")
    @ApiOperation(value = "", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public PatientVO login(String openId) throws BusinessException {
        LOGGER.info("用户登陆 openId:{}", openId);
        // 参数校验
        if (StringUtils.isEmpty(openId)) {
            LOGGER.error("patient login ERROR ; openId is null : openId {}", openId);
            throw new PatientBusinessException(ExceptionCodes.PARAM_ERROR);
        }
        return this.patientService.login(openId);
    }

    /**
     * 获取用户基础信息
     *
     * @param patientId 患者id
     *
     * @return
     *
     * @throws Exception String <参数异常、账户异常>
     * @History 2015年6月24日 下午6:12:54 by Amber
     */
    @ResponseBody
    @RequestMapping("base")
    @ApiOperation(value = "", httpMethod = "POST", produces = "application/json;utf-8")
    @ApiImplicitParams({@ApiImplicitParam(name = "patientId", value = "患者ID", required = true, dataType = "long", paramType = "query")})
    public ResponseVO<PatientVO> getBaseInfo(Long patientId) throws Exception {
        if (null == patientId) {
            patientId = (Long) ResourceHolder.getResource(SettingConfig.PATIENT_ID);
        }
        // 参数校验
        if (patientId == null) {
            LOGGER.error("patient base ERROR ; illegal param : patientId is null");
            throw new PatientBusinessException(ExceptionCodes.PARAM_ERROR);
        }

        LOGGER.info("patient base SUCCESS ; patientId {}", patientId);
        PatientVO patientVo = this.patientService.getPatientBaseInfo(patientId);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS, patientVo);
    }

    /**
     * 保存基础信息 手机号独立于基本信息存储，其他信息可批量编辑。 @2015-09-21 by zhoupeipei
     *
     * @param patientId 患者id
     * @param
     *
     * @return
     *
     * @throws Exception String <返回值描述>
     * @History 2015年6月24日 下午7:24:12 by Amber 2015年9月21日 by Amber
     */
    @ResponseBody
    @RequestMapping(value = "save", method = RequestMethod.POST)
    @ApiOperation(value = "患者保存基础信息 手机号独立于基本信息存储，其他信息可批量编辑", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({@ApiImplicitParam(name = "patientId", value = "患者ID", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "name", value = "姓名", required = false, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "photo", value = "头像", required = false, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "gender", value = "性别(0女1男)", required = false, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "cityId", value = "城市ID", required = false, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "phone", value = "手机号", required = false, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "actionType", value = "操作类型(0/完善信息；1/认证手机号)", required = false, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "idCard", value = "身份证号[PT-2.14.0新增]", required = false, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "birthday", value = "出生日期[yyyy-MM-dd HH:mm:ss]", required = false, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "address", value = "居住详细地址", required = false, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "contactName", value = "紧急联系人姓名", required = false, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "contactPhone", value = "紧急联系人手机号", required = false, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "maritalStatus", value = "婚姻状态(0,未婚；1,已婚)", required = false, dataType = "int", paramType = "query")})
    public ResponseVO<PatientVO> saveBaseInfo(Long patientId, PatientBaseParam patientBaseParam, Integer actionType) throws Exception {
        if (null == patientId) {
            patientId = (Long) ResourceHolder.getResource(SettingConfig.PATIENT_ID);
        }
        // Map<String, Object> result = new HashMap<>();
        LOGGER.info("pateint save info , params : patientId {}, actionType {}, data {}", patientId, actionType,
                    JsonMapper.toJson(patientBaseParam));
        try {
            PatientVO patientVo;
            // 参数校验
            if (patientId == null || (StringUtils.isNotEmpty(patientBaseParam.getPhone()) && actionType == null)) {// 手机号不为空时，需要明确是新增还是修改
                LOGGER.error("patient save ERROR ; illegal param : patientId {},phone {},actionType {}", patientId, patientBaseParam.getPhone(),
                             actionType);
                return PublicService.returnResponseVO(ExceptionCodes.PARAM_ERROR, null);
            }

            // 校验年龄为数字，手机号为数字，且修改手机号时有验证码
            if (!patientBaseParam.saveValidate()) {
                LOGGER.error("patient save ERROR ; illegal param : patientId {},phone {},actionType {}", patientId, patientBaseParam.getPhone(),
                             actionType);
                return PublicService.returnResponseVO(ExceptionCodes.PARAM_ERROR, null);
            }
            // 绑定、修改手机号，验证码校验
            String phone = patientBaseParam.getPhone();
            if (StringUtils.isNotEmpty(phone)) {// 绑定手机
                String code = patientBaseParam.getCode();
                String cacheCode = CommonCacheUtil.getCodeFromRedis(actionType, phone);
                if (cacheCode == null) {// 验证码过期
                    LOGGER.error("patient save ERROR ;cacheCode is expire : patientId {},phone {},actionType {}", patientId,
                                 patientBaseParam.getPhone(), actionType);
                    return PublicService.returnResponseVO(ExceptionCodes.PHONE_CODE_EXPIRE_PT, null);
                } else if (!cacheCode.equals(code)) {// 验证码错误
                    LOGGER.error("patient save ERROR ; code wrong : patientId {},phone {},actionType {}", patientId, patientBaseParam.getPhone(),
                                 actionType);
                    return PublicService.returnResponseVO(ExceptionCodes.PHONE_CODE_WRONG_PT, null);
                }
                // 只更新手机号
                this.patientService.savePhone(patientId, phone);
            }
            patientVo = this.patientService.saveBaseInfo(patientId, patientBaseParam);

            LOGGER.info("patient save SUCCESS ; patientId  {},phone {},name {},actionType {}", patientId, patientBaseParam.getPhone(),
                        patientBaseParam.getName(), actionType);
            return PublicService.returnResponseVO(ExceptionCodes.SUCCESS, patientVo);
        } catch (BusinessException e) {
            return PublicService.returnResponseVO(e.getCode(), null);
        } catch (Exception e) {
            LOGGER.error("保存患者基本信息接口错误 请求参数：patientId = [{}], patientBaseParam = [{}], actionType = [{}]", patientId, patientBaseParam, actionType,
                         e);
            return PublicService.returnResponseVO(ExceptionCodes.FAILED, null);
        }
    }

    /**
     * 获取患者简报
     *
     * @param patientId 患者id
     *
     * @return
     *
     * @throws Exception String <患者简报>
     * @History 2015年6月25日 下午2:49:05 by Amber
     */
    @ResponseBody
    @RequestMapping("simple")
    @ApiOperation(value = "", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams({@ApiImplicitParam(name = "patientId", value = "患者ID", required = true, dataType = "long", paramType = "query")})
    public ResponseVO<PatientVO> getSimple(Long patientId) {
        if (null == patientId) {
            patientId = (Long) ResourceHolder.getResource(SettingConfig.PATIENT_ID);
        }
        try {
            PatientVO patientVo = null;
            // 参数校验
            if (patientId == null) {
                LOGGER.error("patient simple ERROR ; illegal param : patientId is null");
                throw new PatientBusinessException(ExceptionCodes.PARAM_ERROR);
            }

            patientVo = this.patientService.getSimpleInfo(patientId, "");
            LOGGER.info("patient simple SUCCESS ; patientId {}", patientId);
            return PublicService.returnResponseVO(ExceptionCodes.SUCCESS, patientVo);
        } catch (BusinessException e) {
            return PublicService.returnResponseVO(e.getCode(), null);
        } catch (Exception e) {
            LOGGER.error("patient simple ERROR ; patientId {}", patientId, e);
            return PublicService.returnResponseVO(ExceptionCodes.FAILED, null);
        }
    }

    /**
     * 患者提交意见
     *
     * @param patientId  患者id
     * @param suggestion 意见内容
     * @param phone      手机号
     *
     * @return
     *
     * @throws Exception String <返回值描述>
     * @History 2015年6月25日 下午11:19:28 by Amber
     */
    @ResponseBody
    @RequestMapping(value = "suggest", method = RequestMethod.POST)
    @ApiOperation(value = "", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public void suggest(Long patientId, String suggestion, String phone) throws PatientBusinessException {
        if (null == patientId) {
            patientId = (Long) ResourceHolder.getResource(SettingConfig.PATIENT_ID);
        }
        // 表情过滤
        suggestion = NameUtils.handleUtf8mb4(suggestion, "");
        // 参数校验
        if (patientId == null || StringUtils.isEmpty(suggestion)) {
            LOGGER.error("patient suggest ERROR ; illegal param : patientId {},suggestion {}", patientId, suggestion);
            throw new PatientBusinessException(ExceptionCodes.PARAM_ERROR);
        }
        try {
            this.patientService.saveSuggest(patientId, suggestion, phone);
        } catch (PatientBusinessException e) {
            throw new PatientBusinessException(ExceptionCodes.PATIENT_SUGGEST_ERROR, e);
        }
        LOGGER.info("patient suggest SUCCESS ; patientId {},suggestion {}，phone {}", patientId, suggestion, phone);
    }

    /**
     * 获取患者档案
     *
     * @param patientId 患者id
     *
     * @return String <返回值描述>
     *
     * @throws Exception
     * @History 2015年6月28日 下午6:32:10 by Amber
     */
    @ResponseBody
    @RequestMapping("document/get")
    @ApiOperation(value = "", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public MPatientDocument getDocument(Long patientId) throws BusinessException {
        if (null == patientId) {
            patientId = (Long) ResourceHolder.getResource(SettingConfig.PATIENT_ID);
        }
        // 参数校验
        if (patientId == null) {
            LOGGER.error("patient document get ERROR ; illegal param : patientId is null");
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        MPatientDocument patientDocument = this.patientDocumentService.getDocument(patientId);
        if (patientDocument.getMaritalStatus() == null) {
            patientDocument.setMaritalStatus((short) 0);
        }

        LOGGER.info("patient document get SUCCESS ; patientId {}", patientId);
        return patientDocument;
    }

    /**
     * 保存档案
     *
     * @param patientId 患者id
     *
     * @return
     *
     * @throws Exception String <返回值描述>
     * @History 2015年6月26日 上午11:07:52 by Amber
     */
    @ResponseBody
    @RequestMapping(value = "document/save")
    @ApiOperation(value = "", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public MPatientDocument saveDocument(Long patientId, String data) throws Exception {
        if (null == patientId) {
            patientId = (Long) ResourceHolder.getResource(SettingConfig.PATIENT_ID);
        }
        // 参数校验
        if (patientId == null) {
            LOGGER.error("patient document save ERROR ; illegal param : patientId is null,data {}", data);
            throw new PatientBusinessException(ExceptionCodes.PARAM_ERROR);
        }
        List<MPatientDocument> datas = JsonMapper.toList(data, MPatientDocument.class);

        // 参数校验
        if (datas.size() == 0) {
            LOGGER.error("patient document save ERROR ; data format error : patientId {},data {}", patientId, data);
            throw new PatientBusinessException(ExceptionCodes.PARAM_ERROR);
        }
        MPatientDocument base = datas.get(0);

        MPatientDocument result = this.patientDocumentService.saveDocument(patientId, base);
        if (result.getMaritalStatus() == null) {
            result.setMaritalStatus((short) 0);
        }

        LOGGER.info("patient document save SUCCESS ; patientId {},data {}", patientId, data);
        return result;
    }

    /**
     * 删除档案
     * 设置某项档案为无
     *
     * @param patientId 患者id
     * @param data      删除参数
     *
     * @return
     *
     * @throws Exception String <返回值描述>
     * @History 2015年7月1日 上午2:09:44 by Amber
     */
    @ResponseBody
    @RequestMapping(value = "document/delete", method = RequestMethod.POST)
    @ApiOperation(value = "", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public void deleteDocument(Long patientId, String data) throws Exception {
        if (null == patientId) {
            patientId = (Long) ResourceHolder.getResource(SettingConfig.PATIENT_ID);
        }
        LOGGER.error("patient document delete patientId is {}:", patientId);
        // 参数校验
        if (patientId == null) {
            LOGGER.error("patient document delete ERROR ; illegal param : patientId is null ,data {}", data);
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        List<DeleteDocument> datas = JsonMapper.toList(data, DeleteDocument.class);
        // 参数校验
        if (datas.size() == 0) {
            LOGGER.error("patient document delete ERROR ; illegal param : patientId {},data {}", patientId, data);
            throw new PatientBusinessException(ExceptionCodes.PARAM_ERROR);
        }

        LOGGER.info("patient document delete SUCCESS ; illegal param : patientId {},data {}", patientId, data);
    }

    /**
     * uid推送
     *
     * @param unionId 用户唯一标识
     * @param userId  b2c用户id
     *
     * @return String <返回值描述>
     *
     * @throws Exception
     * @History 2015年6月27日 下午2:32:34 by Amber
     */
    @ResponseBody
    @RequestMapping(value = "naiterui/bind", method = RequestMethod.POST)
    @ApiOperation(value = "", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public void b2cCallback(String unionId, Long userId) throws Exception {
        // 参数校验
        if (StringUtils.isEmpty(unionId) || userId == null || userId == 0) {
            LOGGER.error("patient  bind ERROR ; illegal param : unionId {},userId {}", unionId, userId);
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        this.patientService.addUser(unionId, userId);

        LOGGER.info("patient  bind SUCCESS ; unionId {},userId {}", unionId, userId);
    }

    /**
     * 获取患者私人医生信息，是否有私人医生。 PatientController.getPersonalInfo()
     *
     * @param openId
     *
     * @return
     *
     * @throws Exception
     * @Author Amber
     * @Date 2015年12月7日
     * @since 1.0.0
     */
    @ResponseBody
    @RequestMapping(value = "personal/info")
    @ApiOperation(value = "", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public PatientVO getPersonalInfo(String openId) throws Exception {
        // 参数异常
        if (openId == null) {
            LOGGER.error("patient personal info ERROR ; illegal param : openId is null");
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        // 获取患者私人医生信息，是否有私人医生
        PatientVO patientVo = this.patientService.getPersonalInfo(openId);

        LOGGER.info("patient personal info SUCCESS ; openId {}", openId);
        return patientVo;
    }

    /**
     * 获取患者信息，用于b2c生成处方单 PatientController.getPatientInfo()
     *
     * @param unionId
     *
     * @return
     *
     * @throws Exception
     * @Author Amber
     * @Date 2015年12月7日
     * @since 1.0.0
     */
    @ResponseBody
    @RequestMapping(value = "info")
    @ApiOperation(value = "", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public PatientVO getPatientInfo(String unionId) throws Exception {
        if (StringUtils.isEmpty(unionId)) {
            LOGGER.error("patient info ERROR ; illegal param : unionId {}", unionId);
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        PatientVO patientVo = this.patientService.getPatientInfoForB2c(unionId);
        // 成功返回日志
        LOGGER.info("patient info SUCCESS ; unionId {}, result {}", unionId, patientVo);
        return patientVo;
    }

}
